package com.ccll.controller;

import cn.hutool.core.io.IoUtil;
import com.ccll.constants.GlobalConstant;
import com.ccll.domain.common.BaseContextHolder;
import com.ccll.domain.common.CustomException;
import com.ccll.domain.http.Result;
import com.ccll.domain.po.File;
import com.ccll.service.FileService;
import com.ccll.utils.RedisCache;
import com.ccll.utils.validate.MailUtil;
import com.ccll.utils.validate.ValidateCodeUtils;
import lombok.Cleanup;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;

/**
 * @author Seon
 * @date 2022/11/12 20:57
 */
@Slf4j
@RestController
@RequestMapping("/common")
public class CommonController {

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private FileService fileService;


    /**
     * 下载文件
     *
     * @param id 文件的id值
     * @return
     */
    @GetMapping("/download")
    public void download(@RequestParam("id") Long id,
                         HttpServletResponse response) {
        File file = fileService.getById(id);
        try {
            java.io.File testFile = new java.io.File(file.getRealPath());
            if (!testFile.exists()) {
                throw new CustomException("文件不存在");
            }
            response.setContentType("multipart/form-data");
            response.addHeader("Content-Disposition", "attachment; filename=\"" + new String(file.getFileName().getBytes(StandardCharsets.UTF_8), "ISO8859-1") + "\"");
            @Cleanup FileInputStream is = new FileInputStream(file.getRealPath());
            @Cleanup ServletOutputStream os = response.getOutputStream();
            IoUtil.copy(is, os);
            log.info("下载文件成功, fileId = {}", id);
        } catch (IOException e) {
            log.error(e.getMessage());
            throw new CustomException("下载失败,文件已损坏");
        }
    }

    /**
     * 文件上传，只上传一个
     *
     * @param userViewPath 用户前端的可视路径 例如/user/或者/hua/wang/，总之都是以/结尾的。
     * @param file         文件二进制流
     * @return
     */
    @PostMapping("/upload")
    @Transactional
    public Result<?> upload(String userViewPath, MultipartFile file) {
        if (!userViewPath.endsWith("/")) {
            userViewPath += "/";
        }
        Long userId = BaseContextHolder.getCurrentId();
        String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().indexOf("."));
        String finalName = fileService.uploadFile(file);
        String fileType;
        if (Arrays.asList(GlobalConstant.img).contains(suffix)) {
            fileType = "img";
        } else if (Arrays.asList(GlobalConstant.video).contains(suffix)) {
            fileType = "video";
        } else if (Arrays.asList(GlobalConstant.music).contains(suffix)) {
            fileType = "music";
        } else if (Arrays.asList(GlobalConstant.file).contains(suffix)) {
            fileType = "file";
        } else if (Arrays.asList(GlobalConstant.zip).contains(suffix)) {
            fileType = "zip";
        } else {
            fileType = "other";
        }

        File saveFile = File.builder().userId(userId)
                .fileName(file.getOriginalFilename())
                .filePath(userViewPath + file.getOriginalFilename())
                .realPath(finalName)
                .fileType(fileType)
                .fileSize(new BigDecimal(file.getSize() / 1000))
                .isFolder(0)
                .build();
        try {
            fileService.save(saveFile);
            return Result.success(saveFile);
        } catch (Exception e) {
            log.info("上传文件重名, userId = {},  filePath = {}, fileType = {}",
                    userId, userViewPath + file.getOriginalFilename(), fileType);
            return Result.error("由于文件重名，上传文件失败", 0);
        }
    }

    /**
     * 发送验证码。
     *
     * @param email 发送验证码的邮箱
     */
    @GetMapping("/sendCode")
    public Result<?> sendCode(@RequestParam("email") String email) {
        String code = ValidateCodeUtils.generateValidateCode(6).toString();
        String redisKey = GlobalConstant.CAPTCHA + email;
        /*
         * redis主键为 captcha:2963095996@qq.com, 过期时间为五分钟。
         */
        redisCache.setCacheObject(redisKey, code, 5, TimeUnit.MINUTES);
        //发送邮件
        Thread mailThread = new Thread(new MailUtil(email, code));
        mailThread.start();
        log.info("验证码已发送, email = {}, code = {}", email, code);
        return Result.success("获取验证码成功，请及时查收哦");
    }
}
